﻿namespace Stee.CAP8.MessageBus.Sagas.Core.Sagas.SagaData
{
    using Stee.CAP8.MessageBus.Sagas.Core.Ioc;
    using System;
    using System.ComponentModel;
    using Microsoft.Extensions.DependencyInjection;
    using System.Runtime.CompilerServices;
    using System.Reflection;
    using System.Threading;

    using AutoResetEventTest.ISagaStorages;
    using System.Collections.Concurrent;

    public abstract class BaseSagaData : INotifyPropertyChanged
    {
        protected void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        private static ConcurrentDictionary<string, AutoResetEvent> resetEventSource = new ConcurrentDictionary<string, AutoResetEvent>();
        private AutoResetEvent autoResetEvent;
        private void GetResetEvent()
        {
            autoResetEvent = resetEventSource.GetOrAdd(SagaId, new AutoResetEvent(true));

        }

        protected BaseSagaData(string sagaId)
        {
            SagaId = sagaId ?? throw new ArgumentNullException(nameof(sagaId));
            GetResetEvent();
            LoadData();
        }


        private void BaseSagaData_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            autoResetEvent.WaitOne();
            {
                

                Thread.CurrentThread.Join(2000);
                var provider = SagaContainer.ServiceProvider;
                var storage = provider.GetService<ISagaStorage>();

                var propertynfo = GetType().GetProperty(e.PropertyName, BindingFlags.Public | BindingFlags.Instance);
                _ = bool.TryParse(propertynfo?.GetValue(sender).ToString(), out var proValue);

                storage.Insert(SagaId,
                    new SagaDataProperty() { PropertyName = e.PropertyName, PropertyValue = proValue }
                    );
                Console.WriteLine($"存储SagaId={SagaId}-,{e.PropertyName}={proValue}");
            }


            autoResetEvent.Set();


        }

        public bool LoadData()
        {
            autoResetEvent.WaitOne();
            {
                PropertyChanged = null;
                var provider = SagaContainer.ServiceProvider;
                var storage = provider.GetService<ISagaStorage>();
                var properties = storage.Find(SagaId);
                Console.WriteLine("========================================================");
                Console.Write($"从数据库加载SagaId={SagaId}");
                properties?.ForEach(property =>
                {

                    var propertynfo = this.GetType().GetProperty(property.PropertyName, BindingFlags.Public | BindingFlags.Instance);
                    propertynfo?.SetValue(this, property.PropertyValue);
                    Console.Write($"{property.PropertyName}={property.PropertyValue},");

                });
                Console.WriteLine();
                Console.WriteLine("========================================================");
                PropertyChanged = BaseSagaData_PropertyChanged;

                Thread.CurrentThread.Join(2000);
            }
            autoResetEvent.Set();
            return true;

        }

        public event PropertyChangedEventHandler PropertyChanged;

        public string SagaId { get; set; }
        public abstract bool IsDone();

    }
}
